<?php
namespace Tbf\Bundle\CronBundle\Tests;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Tbf\Bundle\TaskManageBundle\MockTask;
use Tbf\Bundle\TestBundle\Logger\ArrayLogger;
use Tbf\Component\CallNum\CallNumFunction;
use Tbf\Component\DateTime\Clock\SystemClock;
use Tbf\Component\DateTime\DateSequence\IntervalDateSequence;
use Tbf\Component\DateTime\DateSequence\OnceDateSequence;
use Tbf\Bundle\CronBundle\CronManager;
use Tbf\Bundle\CronBundle\Entity\Cron;
use Tbf\Component\DateTime\DateTimeFunction;

class CronManageTest extends CronBundleTestCase
{
    public function test1(){
        $this->setDbData(array(
            'tbf_cron'=>array()
        ));
        $seq = new OnceDateSequence(DateTimeFunction::fromMysqlDateTime('2001-01-01 01:01:01'));
        $this->getClientDic()->get('tbf.clock')->setFixTime(DateTimeFunction::fromMysqlDateTime('2001-01-01 01:01:02'));
        $task = new MockTask();
        $cron = new Cron($seq,$task);
        $this->getClientDic()->get('tbf_cron')->addCron($cron);
        $this->assertEquals(0,$task->getCallNum());
        $data = $this->getTableData('tbf_cron');
        $this->assertEquals(1,count($data));
        $this->getClientDic()->get('tbf_cron')->onTrigger();
        $this->assertEquals(1,$task->getCallNum());
        $data = $this->getTableData('tbf_cron');
        $this->assertEquals(0,count($data));
    }

    /**
     * 并发测试
     * 线程1: 加入cron,运行onTrigger,时间点b,结束cron运行
     * 线程2: 在时间点b,运行onTrigger
     * 线程2没有运行cron
     * 可以并入同一个线程...
     */
    public function test2(){
        $this->setDbData(array(
            'tbf_cron'=>array()
        ));
        $seq = new OnceDateSequence(DateTimeFunction::fromMysqlDateTime('2001-01-01 01:01:01'));
        $this->getClientDic()->get('tbf.clock')->setFixTime(DateTimeFunction::fromMysqlDateTime('2001-01-01 01:01:02'));
        $task = new MockTask();
        $task->setCallback(array(get_class($this),'thread2'));
        $cron = new Cron($seq,$task);
        $this->getClientDic()->get('tbf_cron')->addCron($cron);
        $this->getClientDic()->get('tbf_cron')->onTrigger();
        $this->assertEquals(1,$task->getCallNum());
    }
    public static function thread2(ContainerInterface $container){
        $container->get('tbf_cron')->onTrigger();
    }
    /*
    public function testAddCron()
    {
        $cron = $this->newCronMock();
        $repository = $this->newRepositoryMock();
        $repository->expects($this->once())->method('persist')->with($cron);
        $manager = $this->newCronManager($repository);
        $manager->addCron($cron);
    }
    public function testOnTrigger()
    {
        $invalid_cron = $this->newCronMock();
        $invalid_cron->expects($this->never())->method('run');
        $invalid_cron->expects($this->once())->method('isValid')->will($this->returnValue(false));

        $valid_cron = $this->newCronMock();
        $valid_cron->expects($this->once())->method('run');
        $valid_cron->expects($this->exactly(2))->method('isValid')->will($this->returnValue(true));

        $repository = $this->newRepositoryMock();
        $repository->expects($this->once())->method('getNeedRunList')
            ->will($this->returnValue(array($invalid_cron,$valid_cron)));

        $repository->expects($this->once())->method('remove')->with($invalid_cron);
        $repository->expects($this->once())->method('persist')->with($valid_cron);
        $manager = $this->newCronManager($repository);
        $manager->onTrigger();
    }
    */
    /*
    public function testAddCron()
    {
        $this->setDbData(array(
            'tbf_cron'=>array()
        ));
        $input_time = new \DateTime('now');
        $date_sequence = new OnceDateSequence($input_time);
        $task = $this->getMockTask($this->never());
        $cron = new Cron($date_sequence,$task);
        $this->getClientDic()->get('tbf_cron')->addCron($cron);
        $data = $this->getTableData('tbf_cron');
        $this->assertEquals(1,count($data));
        $row = array_pop($data);
        $this->assertEquals($input_time->format('Y-m-d H:i:s'),$row['next_time']);
    }
    public function testOnTrigger()
    {
        $this->setDbData(array(
            'tbf_cron'=>array()
        ));
        $input_time = new \DateTime('now');
        $date_sequence = new OnceDateSequence($input_time);
        $task = $this->getMockTask($this->once());
        $cron = new Cron($date_sequence,$task);
        $this->getClientDic()->get('tbf_cron')->addCron($cron);
        $this->getClientDic()->get('tbf_cron')->onTrigger();
        $data = $this->getTableData('tbf_cron');
        $this->assertEquals(0,count($data));
    }
    public function testOnTriggerWithInterval()
    {
        $this->setDbData(array(
            'tbf_cron'=>array()
        ));
        $start_time = \DateTime::createFromFormat('Y-m-d H:i:s','2000-01-01 01:01:01');
        $interval_time = \DateInterval::createFromDateString('+1 second');
        $date_sequence = new IntervalDateSequence($interval_time,$start_time);
        $task = $this->getMockTask($this->once());
        $cron = new Cron($date_sequence,$task);
        $this->getClientDic()->get('tbf_cron')->addCron($cron);

        $data = $this->getTableData('tbf_cron');
        $this->assertEquals(1,count($data));
        $this->getClientDic()->get('tbf_cron')->onTrigger();

        $data = $this->getTableData('tbf_cron');
        $this->assertEquals(1,count($data));
        $row = array_pop($data);
        $now = new \DateTime('now');
        $this->assertEquals($now->format('Y-m-d H:i:s'),$row['next_time']);
    }
    public function getMockTask($call_number)
    {
        $mock = $this->getMock('Tbf\Bundle\TaskManageBundle\TaskInterface');
        $mock->expects($call_number)
            ->method('run');

        return $mock;
    }
    */
}
